package name.huzhenbo.java.exceptions;

import java.util.HashMap;
import java.util.Map;

/**
 * Actually the best way to deal with exceptions from lower layers is to avoid them entirely by ensuring that lower-level
 * <p/>
 * methods will succeed before invoking them.
 */
class LoginManager {
    private Map<String, String> users;

    public static LoginManager getInstance() {
        return LoginManagerHolder.instance;
    }

    private LoginManager() {
        users = new HashMap<String, String>();
    }

    public void createUser(String userName, String password) throws UserExistedException {
        if (users.containsKey(userName)) {
            // Contain the necessary informtion in the exception, like userName here.
            throw new UserExistedException("User " + userName + " already existed in the system.");
        }
        // in order to ensure failure atomic, the exception check should be before user adding.
        users.put(userName, password);
    }

    // We need a higher level of exception for the system.
    public void notifyClient(Throwable e) throws SystemLoginException {
        // Exception chaining.
        throw new SystemLoginException(e);
    }

    public void login(String userName, String password) throws UserNotExistException {
        if (!users.containsKey(userName)) {
            throw new UserNotExistException("User " + userName + " does not exist in the system.");
        }
        // login implementation omited.
    }

    private static class LoginManagerHolder {
        static final LoginManager instance = new LoginManager();
    }
}
